Wheres
Where Methods
where
Adds a where clause to a query.
query.from( "users" )
.where( "active", "=", 1 );
query.from( "users" ).where( "last_logged_in", ">", query.raw( "NOW()" ) );
query.from( "users" ).where( "active", 1 );
andWhere
This method is simply an alias for where with the combinator set to "and".
orWhere
This method is simply an alias for where with the combinator set to "or".
whereBetween
Adds a where between clause to the query.
query.from( "users" )
.whereBetween( "id", 1, 2 );
If a function or QueryBuilder is passed it is used as a subselect expression.
query.from( "users" )
.whereBetween(
"id",
function( q ) {
q.select( q.raw( "MIN(id)" ) )
.from( "users" )
.where( "email", "bar" );
},
builder.newQuery()
.select( builder.raw( "MAX(id)" ) )
.from( "users" )
.where( "email", "bar" )
);
whereNotBetween
Adds a where not in clause to the query. This behaves identically to the whereBetween method with the negate`flag set to true.
whereColumn
Adds a where clause to a query that compares two columns.
query.from( "users" )
.whereColumn( "first_name", "=", "last_name" );
query.from( "users" )
.whereColumn( "first_name", "last_name" );
query.from( "users" )
.whereColumn( "first_name", query.raw( "LOWER(first_name)" ) );
whereExists
query.from( "orders" )
.whereExists( function( q ) {
q.select( q.raw( 1 ) )
.from( "products" )
.whereColumn( "products.id", "orders.id" );
} );
whereNotExists
Adds a where not in clause to the query. This behaves identically to the whereExists method with the negate`flag set to true.
whereLike
A shortcut for calling where with "like" set as the operator.
query.from( "users" )
.whereLike( "username", "J%" );
whereIn
Adds a where in clause to the query.
Pass single value, a list of values, or an array of values.
query.from( "orders" )
.whereIn( "id", [ 1, 4, 66 ] );
whereNotIn
Adds a where not in clause to the query.
whereRaw
Shorthand to add a raw SQL statement to the where clauses.
query.from( "users" )
.whereRaw(
"id = ? OR email = ? OR is_admin = 1",
[ 1, "foo" ]
);
whereNull
Adds a where null clause to the query.
query.from( "users" )
.whereNull( "id" );
whereNotNull
Adds a where not in clause to the query.
Dynamic Where Methods
qb uses onMissingMethod to provide a few different helpers when working with where... methods.
andWhere... and orWhere...
Every where... method in qb can be called prefixed with either and or or.
query.from( "users" )
.where( "username", "like", "j%" )
.andWhere( function( q ) {
q.where( "isSubscribed", 1 )
.orWhere( "isOnFreeTrial", 1 );
} );
where{Column}
query.from( "users" )
.whereUsername( "like", "j%" )
.whereActive( 1 );
When / Conditionals
If you store the builder object in a variable, you can use if and else statements like you would expect.
var q = query.from( "posts" );
if ( someFlag ) {
q.orderBy( "published_date", "desc" );
}
This works, but breaks chainability. To keep chainability you can use the when helper method.
when
The when helper is used to allow conditional statements when defining queries without using if statements and having to store temporary variables.
query.from( "posts" )
.when( someFlag, function( q ) {
q.orderBy( "published_date", "desc" );
} )
.get();
Selects
select
If you pass no columns to this method, it will default to "*".
.select( [ "fname AS firstName", "age" ] ).from( "users" )
distinct
Calling distinct will cause the query to be executed with the DISTINCT keyword.
.select( "username" ).distinct().from( "users" )
addSelect
This method adds the columns passed to it to the currently selected columns.
.addSelect( [ "fname AS firstName", "age" ] ).from( "users" )
selectRaw
A shortcut to use a raw expression in the select clause.
.selectRaw( "YEAR(birthdate) AS birth_year" ).from( "users" )
subSelect
The subselect is added to the other already selected columns.
.subSelect( "last_login_date", ( q ) => {
q.selectRaw( "MAX(created_date)" ).from( "logins" )
} ) ).from( "users" )
clearSelect
Clears out the selected columns for a query along with any configured select bindings.
.from( "users" )
.select( [ "fname AS firstName", "age" ] )
.clearSelect()
reselect
Clears out the selected columns for a query along with any configured select bindings.
.from( "users" )
.select( [ "fname AS firstName", "age" ] )
.reselect( "username" )
reselectRaw
Clears out the selected columns.
.from( "users" ).select( [ "fname AS firstName", "age" ] )
.reselectRaw( "YEAR(birthdate) AS birth_year" )
Group By and Having
groupBy
Passing a single string will group by that one column.
query.from( "users" )
.groupBy( "country" );
query.from( "users" )
.groupBy( "country,city" );
query.from( "users" )
.groupBy( [ "country", "city" ] );
# Calling groupBy multiple times will to the current groups.
query.from( "users" )
.groupBy( "country" )
.groupBy( "city" );
query.from( "users" )
.groupBy( query.raw( "DATE(created_at)" ) );
having
Adds a having clause to a query.
query.from( "users" )
.groupBy( "email" )
.having( "email", ">", 1 );
`Expressions can be used in place of the column or the value.
query.from( "users" )
.groupBy( "email" )
.having( query.raw( "COUNT(email)" ), ">", 1 );
Limit, Offset, and Pagination
limit
Sets the limit value for the query.
query.from( "users" )
.limit( 5 );
take
Sets the limit value for the query. Alias for limit.
query.from( "users" )
.take( 5 );
offset
Sets the offset value for the query.
query.from( "users" )
.offset( 25 );
forPage
Helper method to calculate the limit and offset given a page number and count per page.
query.from( "users" )
.forPage( 3, 15 );
simplePaginate & paginate
This method combines forPage, count, and get to create a pagination struct alongside the results. Info on the simplePaginate or paginate methods, including custom pagination collectors, can be found in the Retreiving Results section of the documentation.
From
from
Used to set the base table for the query.
query.from( "users" );
table
An alias for from where you like how calling table looks.
query.table( "users" ).insert( { "name" = "jon" } );
fromRaw
Sometimes you need more control over your from clause in order to add grammar specific instructions, such as adding SQL Server table hints to your queries.
query.fromRaw( "[users] u (nolock)" ).get();
fromSub
Complex queries often contain derived tables.
query.select( [ "firstName", "lastName" ] )
.fromSub( "legalUsers", function ( q ) {
q.select( [ "lName as lastName", "fName as firstName" ] )
.from( "users" )
.where( "age", ">=", 21 )
;
} )
.orderBy( "lastName" )
.get()
Order By
The orderBy method seems simple but has a lot of depth depending on the type of arguments you pass in.
Calling orderBy multiple times appends to the order list.
Order By (String)
query.from( "users" )
.orderBy( "email" );
Calling orderBy multiple times will append to the order list.
query.from( "users" )
.orderBy( "email" )
.orderBy( "username", "desc" );
You can also provide an Expression.
query.from( "users" )
.orderBy( query.raw( "DATE(created_at)" ) );
Order By (List)
query.from( "users" )
.orderBy( "email|asc,username", "desc" );
Order By (Array of Strings)
query.from( "users" )
.orderBy( [ "email|asc", "username" ], "desc" );
Order By (Array of Structs)
query.from( "users" )
.orderBy( [
{ "column": "email", "direction": "asc" },
"username"
], "desc" );
Order By (Subquery)
You can order with a subquery using either a function or a QueryBuilder instance.
query.from( "users" )
.orderBy( function( q ) {
q.selectRaw( "MAX(created_date)" )
.from( "logins" )
.whereColumn( "users.id", "logins.user_id" );
} );
Order By Raw
query.from( "users" )
.orderByRaw( "CASE WHEN status = ? THEN 1 ELSE 0 END DESC", [ 1 ] );
clearOrders
Clears the currently configured orders for the query. Usually used by downstream libraries like Quick.
query.from( "users" )
.orderBy( "email" )
.clearOrders();
reorder
Clears configured orders for query and sets the new orders passed in. Any valid argument to orderBy can be passed here. Usually used by downstream libraries like Quick.
query.from( "users" )
.orderBy( "email" )
.reorder( "username" );
Common Table Expressions (i.e. CTEs)
Common Table Expressions (CTEs) allow you to create re-usable temporal result sets.
with
You can build a CTE using a function:
// qb
query.with( "UserCTE", function ( q ) {
q
.select( [ "fName as firstName", "lName as lastName" ] )
.from( "users" )
.where( "disabled", 0 );
} )
.from( "UserCTE" )
.get();
withRecursive
query
.withRecursive( "Hierarchy", function ( q ) {
q.select( [ "Id", "ParentId", "Name", q.raw( "0 AS [Generation]" ) ] )
.from( "Sample" )
.whereNull( "ParentId" )
// use recursion to join the child rows to their parents
.unionAll( function ( q ) {
q.select( [
"child.Id",
"child.ParentId",
"child.Name",
q.raw( "[parent].[Generation] + 1" )
] )
.from( "Sample as child" )
.join( "Hierarchy as parent", "child.ParentId", "parent.Id" );
} );
}, [ "Id", "ParentId", "Name", "Generation" ] )
.from( "Hierarchy" )
.get();
Unions
The query builder also lets you create union statements on your queries using either UNION or UNION ALL strategies.
union
Adds a UNION statement to the query.
query.from( "users" )
.select( "name" )
.where( "id", 1 )
.union( function ( q ) {
q.from( "users" )
.select( "name" )
.where( "id", 2 );
} );
unionAll
Adds a UNION ALL statement to the query.
query.from( "users" )
.select( "name" )
.where( "id", 1 )
.unionAll( function( q ) {
q.from( "users" )
.select( "name" )
.where( "id", 2 );
} );
Joins
Join clauses range from simple to complex including joining complete subqueries on multiple conditions. qb has your back with all of these use cases.
join
Applies a join to the query. The simplest join is to a table based on two columns:
query.from( "users" )
.join( "posts", "users.id", "=", "posts.author_id" );
When doing a simple join using = as the operator, you can omit it and pass just the column names:
query.from( "users" )
.join( "posts", "users.id", "posts.author_id" );
joinWhere
Adds a join to another table based on a WHERE clause instead of an ON clause.
query.from( "users" )
.joinWhere( "contacts", "contacts.balance", "<", 100 );
For complex joins, a function can be passed to first.
joinRaw
Uses the raw SQL provided to as the table for the join clause.
query.from( "users" )
.joinRaw( "posts (nolock)", "users.id", "posts.author_id" );
Using joinRaw will most likely tie your code to a specific database
joinSub
Adds a join to a derived table. All the functionality of the join method applies to constrain the query.
var sub = query.newQuery()
.select( "id" )
.from( "contacts" )
.whereNotIn( "id", [ 1, 2, 3 ] );
query.from( "users as u" )
.joinSub( "c", sub, "u.id", "=", "c.id" );
leftJoin
query.from( "posts" )
.leftJoin( "users", "users.id", "posts.author_id" );
leftJoinRaw
Uses the raw SQL provided to as the table for the left join clause. All the other functionality of leftJoinRaw matches the join method.
query.from( "posts" )
.leftJoinRaw( "users (nolock)", "users.id", "posts.author_id" );
leftJoinSub
Adds a left join to a derived table.
var sub = query.newQuery()
.select( "id" )
.from( "contacts" )
.whereNotIn( "id", [ 1, 2, 3 ] );
query.from( "users as u" )
.leftJoinSub( "c", sub, "u.id", "=", "c.id" );
rightJoin
query.from( "users" )
.rightJoin( "posts", "users.id", "posts.author_id" );
rightJoinRaw
Uses the raw SQL provided to as the table for the right join clause.
query.from( "users" )
.rightJoinRaw( "posts (nolock)", "users.id", "posts.author_id" );
Using rightJoinRaw will most likely tie your code to a specific database.
rightJoinSub
Adds a right join to a derived table.
var sub = query.newQuery()
.select( "id" )
.from( "contacts" )
.whereNotIn( "id", [ 1, 2, 3 ] );
query.from( "users as u" )
.rightJoinSub( "c", sub, "u.id", "=", "c.id" );
crossJoin
query.from( "users" ).crossJoin( "posts" );
crossJoinRaw
Uses the raw SQL provided to as the table for the cross join clause. Cross joins cannot be further constrained with on or where clauses.
query.from( "users" ).crossJoinRaw( "posts (nolock)" );
crossJoinSub
Adds a cross join to a derived table. The derived table can be defined using a QueryBuilder instance or a function just as with joinSub.
var sub = query.newQuery()
.select( "id" )
.from( "contacts" )
.whereNotIn( "id", [ 1, 2, 3 ] );
query.from( "users as u" ).crossJoinSub( "c", sub );
newJoin
var j = query.newJoin( "contacts" )
.on( "users.id", "posts.author_id" );
query.from( "users" ).join( j );
// This is still an inner join because
// the JoinClause is an inner join
var j = query.newJoin( "contacts", "inner" )
.on( "users.id", "posts.author_id" );
query.from( "users" ).leftJoin( j );
JoinClause
A JoinClause is a specialized version of a QueryBuilder. You may call on or orOn to constrain the JoinClause. You may also call any where methods.
on
Applies a join condition to the JoinClause. An alias for whereColumn.
var j = query.newJoin( "contacts" )
.on( "users.id", "posts.author_id" );
query.from( "users" ).join( j );
orOn
Applies a join condition to the JoinClause using an or combinator. An alias for orWhereColumn.
var j = query.newJoin( "contacts" )
.on( "users.id", "posts.author_id" )
.orOn( "users.id", "posts.reviewer_id" );
query.from( "users" ).join( j );
Preventing Duplicate Joins
You can optionally configure qb to ignore duplicate joins.
moduleSettings = {
"qb": {
"preventDuplicateJoins": true
}
};
Retrieving Results
get
The get method is the most common method used for retrieving results.
query.from( "users" ).get();
`get can also take a list or array of columns to use as a shortcut.
query.from( "users" ).get( [ "id", "name" ] );
first
If you just need to retrieve a single row from the database table, you may use the first method.
query.from( "users" ).first();
values
If you don't even need an entire row, you may extract a single value from each record using the values method.
query.from( "users" ).values( "firstName" );
[ "jon", "jane", "jill", ...
]
value
This method is similar to values except it only returns a single, simple value.
query.from( "users" ).value( "firstName" );
"jon"
If no records are returned from the query, one of two things will happen.
chunk
Large datasets can be broken up and retrieved in chunks.
query.from( "users" ).chunk( 100, function( users ) {
// Process the users here
// Returning false from the callback stops processing
} );
paginate
Generates a pagination struct along with the results of the executed query.
query.from( "users" )
.paginate();
{
"pagination": {
"maxRows": 25,
"offset": 0,
"page": 1,
"totalPages": 2,
"totalRecords": 45
},
"results": [ { /* ... */ }, ]
}
simplePaginate
Generates a simple pagination struct along with the results of the executed query.
query.from( "users" )
.simplePaginate();
{
"pagination": {
"maxRows": 25,
"offset": 0,
"page": 1,
"hasMore": true
},
"results": [ { /* ... */ }, ]
}
Custom Pagination Collectors
A pagination collector is the name given to the struct returned from calling the paginate method.
generateWithResults
You can set your custom pagination collector either in the constructor using the paginationCollector argument or by calling setPaginationCollector on a query builder instance.
Inserts, Updates, and Deletes
insert
This call must come after setting the query's table using from or table.
You can insert a single record by passing a struct:
query.from( "users" )
.insert( {
"name" = "Robert",
"email" = "robert@test.com",
"age" = 55
} );
You can specify any query param.
query.from( "users" )
.insert( {
"name" = "Robert",
"email" = "robert@test.com",
"age" = { value = 55, cfsqltype = "CF_SQL_INTEGER" }
} );
Raw values can be supplied to an insert statement.
query.from( "users" )
.insert( {
"name" = "Robert",
"email" = "robert@test.com",
"updatedDate" = query.raw( "NOW()" )
} );
Multiple rows can be inserted in a batch by passing an array of structs to insert.
query.from( "users" ).insert( [
{ "email" = "john@example.com", "name" = "John Doe" },
{ "email" = "jane@example.com", "name" = "Jane Doe" }
] );
returning
Returning is only supported in PostgresGrammar and SqlServerGrammar.
Specifies columns to be returned from the insert query.
query.from( "users" )
.returning( "id" )
.insert( {
"email" = "foo",
"name" = "bar"
} );
update
This call must come after setting the query's table using from or table.
Updates a table with a struct of column and value pairs.
query.from( "users" )
.update( {
"email" = "foo",
"name" = "bar"
} );
You can specify any query param
query.from( "users" )
.update( {
"email" = "foo",
"name" = "bar",
"updatedDate" = { value = now(), cfsqltype = "CF_SQL_TIMESTAMP" }
} );
Any constraining of the update query should be done using the appropriate WHERE statement before calling update.
query.from( "users" )
.whereId( 1 )
.update( {
"email" = "foo",
"name" = "bar"
} );
You can update a column based on another column using a raw expression.
query.from( "hits" )
.where( "page", "someUrl" )
.update( {
"count" = query.raw( "count + 1" )
} );
Updating Null values
Null values can be inserted by using queryparam syntax:
if you are using Lucee with full null support the following (easier) syntax is also allowed:
addUpdate
Adds values to a later update, similar to addSelect.
query.from( "users" )
.whereId( 1 )
.addUpdate( {
"email" = "foo",
"name" = "bar"
} )
.when( true, function( q ) {
q.addUpdate( {
"foo": "yes"
} );
} )
.when( false, function( q ) {
q.addUpdate( {
"bar": "no"
} );
} )
.update();
updateOrInsert
Performs an update statement if the configured query returns true for exists. Otherwise, performs an insert statement.
query.from( "users" )
.where( "email", "foo" )
.updateOrInsert( {
"email" = "foo",
"name" = "baz"
} );
If the configured query returns 0 records, then an insert statement is performed.
query.from( "users" )
.where( "email", "foo" )
.updateOrInsert( {
"email" = "foo",
"name" = "baz"
} );
delete
Deletes all records that the query returns.
query.from( "users" )
.where( "email", "foo" )
.delete();
The id argument is a convenience to delete a single record by id.
query.from( "users" )
.delete( 1 );
Aggregates
The query builder also provides a variety of aggregate methods such as count, max, min, and sum.
exists
Returns true if the query returns any rows. Returns false otherwise.
query.from( "users" ).where( "username", "like", "jon%" ).exists();
count
Returns an integer number of rows returned by the query.
query.from( "users" ).count();
max
Returns the maximum value for the given column.
query.from( "users" ).max( "age" );
min
Returns the minimum value for the given column.
query.from( "users" ).min( "age" );
sum
Returns the sum of all returned rows for the given column.
query.from( "employees" ).sum( "salary" );
Query Parameters and Bindings
Custom Parameter Types
When passing a parameter to qb, it will infer the sql type to be used. You can pass a struct with the parameters you would pass to cfqueryparam.
query.from( "users" )
.where( "id", "=", { value = 18, cfsqltype = "CF_SQL_VARCHAR" } );
This can be used when inserting or updating records as well.
query.table( "users" )
.insert( {
"id" = { value 1, cfsqltype = "CF_SQL_VARCHAR" },
"age" = 18,
"updatedDate" = { value = now(), cfsqltype = "CF_SQL_DATE" }
} );
Strict Date Detection
By default, qb will try to determine if a variable is a date using the built-in isDate function.
moduleSettings = {
"qb": {
"strictDateDetection": true
}
};
Numeric SQL Type
By default, qb will use the CF_SQL_NUMERIC SQL type when it detects a numeric binding.
moduleSettings = {
"qb": {
"numericSQLType": "CF_SQL_INTEGER"
}
};
Bindings
Bindings are the values that will be sent as parameters to a prepared SQL statement.
getBindings
This method returns the current bindings in order to be used for the query.
query.from( "users" )
.join( "logins", function( j ) {
j.on( "users.id", "logins.user_id" );
j.where( "logins.created_date", ">", dateAdd( "m", -1, "01 Jun 2019" ) );
} )
.where( "active", 1 );
You can also retrieve the bindings associated to their corresponding types.
getRawBindings
This method returns the current bindings to be used for the query associated to their corresponding types.
query.from( "users" )
.join( "logins", function( j ) {
j.on( "users.id", "logins.user_id" );
j.where( "logins.created_date", ">", dateAdd( "m", -1, "01 Jun 2019" ) );
} )
.where( "active", 1 );
Raw Expressions
Raw expressions are the qb escape hatch.
raw
The sql snippet passed to raw is not processed by qb at all.
query.from( "users" ).select( query.raw( "MAX(created_date)" ) );